import smtplib
import glob
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
import os
import time
from dotenv import load_dotenv
import logging
from queue import Queue
from threading import Thread
import html

load_dotenv()

# 配置基本日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)

class MailSender:
    def __init__(self):
        self.smtp_server = os.getenv('SMTP_SERVER')
        self.smtp_port = int(os.getenv('SMTP_PORT', 587))
        self.smtp_user = os.getenv('SMTP_USER')
        self.smtp_password = os.getenv('SMTP_PASSWORD')
        self.recipients = os.getenv('REPORT_RECIPIENTS', '').split(',')
        self.max_retries = int(os.getenv('SMTP_MAX_RETRIES', 3))
        self.retry_delay = int(os.getenv('SMTP_RETRY_DELAY', 5))
        
        # 配置日志
        self.logger = logging.getLogger('MailSender')
        
        # 邮件队列
        self.mail_queue = Queue()
        self.queue_worker = Thread(target=self._process_mail_queue, daemon=True)
        self.queue_worker.start()
    
    def _process_mail_queue(self):
        """处理邮件队列的后台线程"""
        while True:
            try:
                if not self.mail_queue.empty():
                    mail_data = self.mail_queue.get()
                    success = self._send_email_with_retry(
                        mail_data['subject'],
                        mail_data['content'],
                        mail_data['html_content'],
                        mail_data['attachments'],
                        mail_data['is_test']
                    )
                    if success:
                        self.logger.info(f"队列中的邮件已发送成功: {mail_data['subject']}")
                    else:
                        self.logger.error(f"队列中的邮件发送失败: {mail_data['subject']}")
                    self.mail_queue.task_done()
                else:
                    time.sleep(1)
            except Exception as e:
                self.logger.error(f"邮件队列处理异常: {e}")
                time.sleep(5)
    
    def send_email(self, subject, content, attachments=None, is_test=False, html_content=None, queue=False):
        """发送邮件，支持普通文本和HTML格式"""
        if not self.smtp_server or not self.smtp_user or not self.smtp_password:
            self.logger.error('邮件配置不完整，无法发送邮件')
            return False
            
        if not self.recipients:
            self.logger.warning('没有配置收件人列表')
            return False
        
        # 如果启用队列模式，将邮件放入队列
        if queue:
            self.mail_queue.put({
                'subject': subject,
                'content': content,
                'html_content': html_content,
                'attachments': attachments,
                'is_test': is_test
            })
            self.logger.info(f"邮件已加入发送队列: {subject}")
            return True
        
        # 直接发送邮件
        return self._send_email_with_retry(subject, content, html_content, attachments, is_test)
    
    def _send_email_with_retry(self, subject, content, html_content=None, attachments=None, is_test=False):
        try:
            with open('crawler.log', 'a', encoding='utf-8') as log_file:
                log_file.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - MailSender - INFO - 邮件发送成功: {subject}\n")
        except Exception as e:
            self.logger.error(f'写入日志失败: {e}')
        msg = MIMEMultipart('alternative')
        msg['From'] = self.smtp_user
        msg['To'] = ', '.join(self.recipients)
        msg['Subject'] = subject
        
        # 添加纯文本内容
        msg.attach(MIMEText(content, 'plain', 'utf-8'))
        
        # 如果提供了HTML内容，添加HTML部分
        if html_content:
            msg.attach(MIMEText(html_content, 'html', 'utf-8'))
        elif content:  # 如果没有HTML但有纯文本，自动转换为简单HTML
            simple_html = f"<html><body><pre>{html.escape(content)}</pre></body></html>"
            msg.attach(MIMEText(simple_html, 'html', 'utf-8'))
        
        # 添加附件
        if attachments:
            for attachment in attachments:
                if os.path.exists(attachment):
                    try:
                        with open(attachment, 'rb') as f:
                            part = MIMEApplication(f.read(), Name=os.path.basename(attachment))
                        part['Content-Disposition'] = f'attachment; filename="{os.path.basename(attachment)}"'
                        msg.attach(part)
                        self.logger.info(f'已成功添加附件: {attachment}')
                    except Exception as e:
                        self.logger.error(f'添加附件失败: {attachment}, 错误: {e}')
                        continue
                else:
                    self.logger.error(f'附件不存在: {attachment}')
        
        # 重试机制
        for attempt in range(self.max_retries):
            try:
                with smtplib.SMTP(self.smtp_server, self.smtp_port) as server:
                    server.set_debuglevel(1 if is_test else 0)
                    server.starttls()
                    server.login(self.smtp_user, self.smtp_password)
                    
                    # 添加NOOP命令检查连接状态
                    try:
                        server.noop()
                    except:
                        self.logger.warning("连接异常，重新建立连接")
                        server.quit()
                        continue
                    
                    # 发送邮件
                    try:
                        response = server.sendmail(self.smtp_user, self.recipients, msg.as_string())
                        server.quit()  # 明确关闭连接
                        self.logger.info(f'邮件发送成功: {subject}')
                        return True if not response else False
                    except smtplib.SMTPResponseException as e:
                        self.logger.error(f'邮件发送后服务器返回错误: {e.smtp_error.decode()}')
                        server.quit()
                        continue
                    
            except smtplib.SMTPServerDisconnected as e:
                self.logger.warning(f'SMTP服务器连接断开 (尝试 {attempt+1}/{self.max_retries}): {e}')
            except smtplib.SMTPAuthenticationError as e:
                self.logger.error(f'SMTP认证失败: {e}')
                return False  # 认证失败不重试
            except smtplib.SMTPException as e:
                self.logger.warning(f'SMTP协议错误 (尝试 {attempt+1}/{self.max_retries}): {e.smtp_error.decode() if hasattr(e, "smtp_error") else str(e)}')
            except Exception as e:
                self.logger.warning(f'邮件发送失败 (尝试 {attempt+1}/{self.max_retries}): {e}')
            
            if attempt < self.max_retries - 1:
                time.sleep(self.retry_delay)  # 延迟一段时间后重试
        
            self.logger.error(f'邮件发送失败，已达到最大重试次数: {subject}')
            return False
                
    def send_reports(self, report_files=None, use_html=True, use_queue=False):
        """发送报告邮件"""
        try:
            print(f"尝试连接SMTP服务器: {self.smtp_server}:{self.smtp_port}")
            with smtplib.SMTP(self.smtp_server, self.smtp_port) as server:
                server.starttls()
                server.login(self.smtp_user, self.smtp_password)
                print("SMTP登录成功")
                
                # 获取所有平台的最新报告
                reports_dir = os.getenv('STORAGE_PATH', './reports')
                
                # 如果没有传入报告文件列表，则自动搜索
                if not report_files:
                    all_reports = glob.glob(os.path.join(reports_dir, '*_report_*.docx'))
                    
                    if not all_reports:
                        self.logger.warning('没有找到报告文件，无法发送邮件')
                        return False
                    
                    # 按修改时间排序
                    all_reports.sort(key=lambda x: os.path.getmtime(x), reverse=True)
                    
                    # 获取每个平台最新的报告
                    platforms = ['weibo', 'douyin', 'zhihu', 'toutiao']
                    latest_reports = []
                    
                    for platform in platforms:
                        platform_reports = [r for r in all_reports if os.path.basename(r).startswith(f"{platform}_")]
                        if platform_reports:
                            latest_reports.append(platform_reports[0])
                            self.logger.info(f"找到{platform}最新报告: {platform_reports[0]}")
                    
                    # 查找综合分析报告
                    summary_reports = [r for r in all_reports if os.path.basename(r).startswith("summary_report_")]
                    if summary_reports:
                        latest_reports.append(summary_reports[0])
                        self.logger.info(f"找到综合分析报告: {summary_reports[0]}")
                    
                    report_files = latest_reports
                
                if not report_files:
                    self.logger.warning('没有找到任何平台的最新报告')
                    return False
                
                # 准备邮件内容
                plain_content = '请查看附件中的最新社交媒体热点分析报告。\n\n此邮件由系统自动发送，请勿回复。'
                
                # 如果使用HTML格式，创建美观的HTML邮件
                html_content = None
                if use_html:
                    # 提取平台名称和报告类型
                    platforms = []
                    has_summary = False
                    
                    for report in report_files:
                        basename = os.path.basename(report)
                        if basename.startswith("summary_report_"):
                            has_summary = True
                        else:
                            platform = basename.split('_')[0]
                            platforms.append(platform)
                    
                    html_content = f"""
                    <html>
                    <head>
                        <style>
                            body {{ 
                                font-family: 'Microsoft YaHei', Arial, sans-serif; 
                                line-height: 1.8; 
                                color: #333;
                                background-color: #f9f9f9;
                                padding: 20px;
                            }}
                            .container {{ 
                                max-width: 800px; 
                                margin: 0 auto; 
                                padding: 30px;
                                background: white;
                                border-radius: 8px;
                                box-shadow: 0 2px 10px rgba(0,0,0,0.1);
                            }}
                            h1 {{ 
                                color: #2c3e50; 
                                border-bottom: 2px solid #eee; 
                                padding-bottom: 15px;
                                margin-bottom: 25px;
                            }}
                            .highlight {{
                                background-color: #f8f9fa;
                                border-left: 4px solid #3498db;
                                padding: 15px;
                                margin: 20px 0;
                            }}
                            .footer {{ 
                                margin-top: 40px; 
                                font-size: 13px; 
                                color: #95a5a6; 
                                text-align: center;
                                border-top: 1px solid #eee;
                                padding-top: 20px;
                            }}
                        </style>
                    </head>
                    <body>
                        <div class="container">
                            <h1>社交媒体热点分析报告</h1>
                            <p>尊敬的用户：</p>
                            <p>附件中包含了以下内容：</p>
                            <ul>
                                {''.join([f'<li><strong>{platform}</strong> 平台热点分析报告</li>' for platform in platforms])}
                                {f'<li><strong class="highlight">多平台热点综合分析报告</strong> (重点关注财经、社会、政策趋势)</li>' if has_summary else ''}
                            </ul>
                            <div class="footer">
                                <p>此报告由系统自动生成，请查看附件获取完整内容</p>
                                <p>生成时间：{time.strftime('%Y-%m-%d %H:%M:%S')}</p>
                            </div>
                        </div>
                    </body>
                    </html>
                    """
                
                # 发送邮件
                success = self.send_email(
                    '社交媒体热点分析报告', 
                    plain_content,
                    attachments=report_files,
                    html_content=html_content,
                    queue=use_queue
                )
                
                if success:
                    self.logger.info(f"成功发送报告邮件，包含平台: {', '.join([os.path.basename(report).split('_')[0] for report in report_files if not os.path.basename(report).startswith('summary_')])}")
                    if any(os.path.basename(report).startswith('summary_') for report in report_files):
                        self.logger.info("邮件中包含综合分析报告")
                
                return success
        except Exception as e:
            print(f"邮件发送失败: {str(e)}")
            self.logger.error(f"邮件发送失败: {str(e)}")
            return False
                    
        def send_test_email(self, use_html=True):
            """发送测试邮件"""
            marker_file = '.test_sent'
            if os.path.exists(marker_file):
                self.logger.info('测试邮件已发送过，不再重复发送')
                return False
                
            # 添加测试附件
            test_attachment = os.path.join(os.path.dirname(__file__), 'test_attachment.txt')
            with open(test_attachment, 'w', encoding='utf-8') as f:
                f.write('这是一个测试附件')
            
            plain_content = '这是一封测试邮件，用于验证邮件发送功能是否正常。'
            html_content = None
            
            if use_html:
                html_content = """
                <html>
                <head>
                    <style>
                        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
                        .container { max-width: 600px; margin: 0 auto; padding: 20px; }
                        h1 { color: #2c3e50; }
                        .test-box { background-color: #f8f9fa; border-left: 4px solid #3498db; padding: 15px; margin: 20px 0; }
                        .footer { margin-top: 30px; font-size: 12px; color: #7f8c8d; text-align: center; }
                    </style>
                </head>
                <body>
                    <div class="container">
                        <h1>邮件系统测试</h1>
                        <p>您好，</p>
                        <div class="test-box">
                            <p>这是一封测试邮件，用于验证邮件发送功能是否正常。</p>
                            <p>如果您收到此邮件，说明邮件系统配置正确。</p>
                        </div>
                        <p>系统信息:</p>
                        <ul>
                            <li>SMTP服务器: {self.smtp_server}</li>
                            <li>发送时间: {time.strftime('%Y-%m-%d %H:%M:%S')}</li>
                        </ul>
                        <div class="footer">
                            <p>此邮件由系统自动发送，请勿回复。</p>
                        </div>
                    </div>
                </body>
                </html>
                """
                
            success = self.send_email(
                '测试邮件', 
                plain_content, 
                attachments=[test_attachment],
                html_content=html_content,
                is_test=True
            )
            
            if success:
                with open(marker_file, 'w') as f:
                    f.write('1')
                self.logger.info('测试邮件发送成功')
            else:
                self.logger.error('测试邮件发送失败')
                
            return success

if __name__ == '__main__':
    mailer = MailSender()
    
    # 发送测试邮件
    if os.getenv('SEND_TEST_EMAIL', 'false').lower() == 'true':
        mailer.send_test_email(use_html=True)
    
    # 发送正式报告邮件
    if os.getenv('SEND_REPORTS', 'true').lower() == 'true':
        mailer.send_reports(use_html=True, use_queue=False)
    else:
        logging.info('报告邮件发送功能已禁用，如需启用请设置环境变量 SEND_REPORTS=true')


    def _format_platform_summary(self, summary):
        """格式化平台摘要内容"""
        platform = summary.split('</h3>')[0].replace('<h3>','')
        content = summary.split('<p>')[1].split('</p>')[0]
        
        # 提取事件列表
        events = []
        current_event = None
        for line in content.split('\n'):
            if line.startswith('## '):
                if current_event:
                    events.append(current_event)
                current_event = {'title': line.replace('## ', '').strip(), 'details': []}
            elif line.startswith('- ') or line.startswith('* '):
                if current_event:
                    current_event['details'].append(line.replace('- ', '').replace('* ', '').strip())
        
        if current_event:
            events.append(current_event)
        
        # 生成HTML
        html = f'<div class="platform-title">{platform}</div>'
        html += '<div class="event-list">'
        
        for event in events:
            html += f'''
            <div class="event-item">
                <div class="event-name">{event['title']}</div>
                <div class="event-detail">
                    {''.join([f'<p>{detail}</p>' for detail in event['details']])}
                </div>
            </div>
            '''
        
        html += '</div>'
        return html


def send_reports(self, report_files):
    msg = MIMEMultipart()
    msg['Subject'] = '社交媒体热点分析报告'
    msg['From'] = self.sender
    msg['To'] = self.recipients
    
    # 添加正文
    text = MIMEText("附件是各平台热点分析报告", 'plain', 'utf-8')
    msg.attach(text)
    
    # 逐个添加附件（带错误处理）
    success_files = []
    for filepath in report_files:
        try:
            with open(filepath, 'rb') as f:
                part = MIMEApplication(f.read())
                part.add_header('Content-Disposition', 'attachment', 
                              filename=os.path.basename(filepath))
                msg.attach(part)
                success_files.append(filepath)
        except Exception as e:
            logging.error(f'添加附件失败: {filepath}, 错误: {e}')
    
    if not success_files:
        logging.error('没有可发送的有效报告')
        return False
    
    # 发送邮件
    try:
        with smtplib.SMTP(self.smtp_server, self.smtp_port) as server:
            server.starttls()
            server.login(self.smtp_user, self.smtp_password)
            server.send_message(msg)
        logging.info(f'邮件发送成功，包含附件: {", ".join(os.path.basename(f) for f in success_files)}')
        return True
    except Exception as e:
        logging.error(f'邮件发送失败: {e}')
        return False